package dat255.calendarclock.view;

import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedList;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.Spinner;
import dat255.calendarclock.controller.event.ShowEventController;
import dat255.calendarclock.model.event.EventHandler;
import dat255.calendarclock.model.event.SubEvent;

/**
 * A 24h-clock used to display events.
 * 
 * @author Marcus Hultman & krabban, and Oskar Montin at a little corner... !!
 *         :D
 * 
 */
public class ClockCalendarView extends LinearLayout {

	// Fields

	private static final int HOURS = 24;

	private static final float HOURSHAND_LENGTH = 0.6f;
	private static final float MINUTESHAND_LENGTH = 0.8f;
	private static final float SECONDSHAND_LENGTH = 0.85f;

	private static float LABEL_OFFSET = 4 / 3f;

	private Paint labelPaint = new Paint();

	private Paint handPaint = new Paint();
	private Paint handSecondaryPaint = new Paint();

	private Paint eventPaint = new Paint();

	private LinkedList<SubEvent> events = new LinkedList<SubEvent>();
	private LinkedList<Float> eventAngles= new LinkedList<Float>();

	private GestureDetector gestureDetector;
	private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
		public boolean onDown(MotionEvent e) {
			float x = e.getX() - getWidth() / 2, y = e.getY() - getHeight() / 2;
			int angle = (int) (180 * (Math.atan2(-y, x - 1) / Math.PI));
			int minAngle = angle - 10, maxAngle = angle + 10;
			final LinkedList<SubEvent> selectedEvents = new LinkedList<SubEvent>();
			for (int i = 0; i < eventAngles.size(); i++) {
				if (eventAngles.get(i) > minAngle && eventAngles.get(i) < maxAngle){
					selectedEvents.add(events.get(i));
					
					Log.d("debug", "Peg " + (i + 1));
					
				}
			}
			if (!selectedEvents.isEmpty()) {
				if (selectedEvents.size() == 1){
					EventHandler.getInstance().setSelectedEvent(selectedEvents.getFirst());
					((Activity) getContext()).startActivity(new Intent(
							getContext(), ShowEventController.class));
				}
				else{
					
					AlertDialog.Builder dropdown = new AlertDialog.Builder(getContext());
					
					ArrayAdapter<SubEvent> adapter = new ArrayAdapter<SubEvent>(
							getContext(), android.R.layout.simple_spinner_item,
							selectedEvents);
					
					;

					dropdown.setSingleChoiceItems(adapter, -1, new android.content.DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							EventHandler.getInstance().setSelectedEvent(selectedEvents.get(which));
							((Activity) getContext()).startActivity(new Intent(
									getContext(), ShowEventController.class));
						}
					});
					
					dropdown.show();
					
					
//					spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
//						
//						@Override
//						public void onNothingSelected(AdapterView<?> arg0) {}
//
//						@Override
//						public void onItemSelected(AdapterView<?> adapter,
//								View view, int index, long arg3) {
//							EventHandler.getInstance().setSelectedEvent(selectedEvents.get(index));
//							((Activity) getContext()).startActivity(new Intent(
//									getContext(), ShowEventController.class));
//						}
//					});
//					
//					spinner.setAdapter(adapter);
//					spinner.showContextMenu();
				}
			}
			return false;
		}
	};

	// Constructor

	public ClockCalendarView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setWillNotDraw(false);
	
		labelPaint.setColor(Color.WHITE);
		handPaint.setColor(Color.WHITE);
		handSecondaryPaint.setColor(Color.RED);

		eventPaint.setStrokeWidth(3);

		loadEvents();

		gestureDetector = new GestureDetector(this.getContext(), gestureListener);
		
	}

	// Initialization

	/**
	 * Loads this clock view when the day has changed
	 * 
	 * @param precision
	 */
	public void loadEvents() {

		// Get our eventhandler
		EventHandler eventHandler = EventHandler.getInstance();
		// Adds all events
		events.clear();
		eventAngles.clear();
		LinkedList<SubEvent> subEvents = eventHandler.getEvents(eventHandler.getSelectedDay(),
				GregorianCalendar.DATE);
		events.addAll(subEvents);
		for (SubEvent subEvent : events) {
			int eventTimeHour = subEvent.getDate().get(GregorianCalendar.HOUR_OF_DAY);
			int eventTimeMinute = subEvent.getDate().get(GregorianCalendar.MINUTE);
			float angle = (float) (Math.PI / 2 - (eventTimeHour / 12.0f + eventTimeMinute / 1440.0f) * Math.PI);
			eventAngles.add((float) Math.toDegrees(angle));
		}
	}

	// Public methods

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return gestureDetector.onTouchEvent(event);
	}
	
	@Override
	protected void onDraw(Canvas canvas) {

		int radius = getWidth() / 4;

		labelPaint.setTextSize(getWidth() / 20);
		labelPaint.setStrokeWidth(getWidth() / 100);
		handPaint.setStrokeWidth(getWidth() / 50);
		handSecondaryPaint.setStrokeWidth(getWidth() / 100);

		int x = getWidth() / 2;
		int y = getHeight() / 2;

		int w = (int) radius;
		int h = (int) radius;

		boolean scaled = false;

		if (getWidth() < w || getHeight() < h) {
			scaled = true;
			float scale = Math.min((float) getWidth() / (float) w,
					(float) getHeight() / (float) h);
			canvas.save();
			canvas.scale(scale, scale, x, y);
		}

		// Time labels
		for (int i = 0; i < HOURS; i++) {

			float angle = (float) (i * Math.PI * 2 / HOURS);

			if (i % 2 == 0) {
				String label = String.format("%02d", i) + "h";
				float labelWidth = labelPaint.measureText(label) / 2;
				float labelHeight = labelPaint.getTextSize() / 2;
				canvas.drawText(
						label,
						getWidth()
								/ 2
								+ (float) (Math.sin(angle) * LABEL_OFFSET * radius)
								- labelWidth,
						getHeight()
								/ 2
								+ (float) (-Math.cos(angle) * LABEL_OFFSET * radius)
								+ labelHeight, labelPaint);
				canvas.drawPoint(getWidth() / 2
						+ (float) (Math.sin(angle) * radius), getHeight() / 2
						+ (float) (-Math.cos(angle) * radius), handPaint);
			} else {
				canvas.drawPoint(getWidth() / 2
						+ (float) (Math.sin(angle) * radius), getHeight() / 2
						+ (float) (-Math.cos(angle) * radius), labelPaint);
			}
		}

		Date date = new Date();
		float mHour = date.getHours();
		float mMinutes = date.getMinutes();
		float mSeconds = date.getSeconds();

		float originRadius = getWidth() / 50;

		// Origin
		canvas.drawCircle(getWidth() / 2, getHeight() / 2, originRadius,
				labelPaint);

		// Hands
		
		double angle = Math.PI / 2 - mMinutes / 30.0f * Math.PI;
		
		canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2
				+ (float) (Math.cos(angle)
						* MINUTESHAND_LENGTH * radius), getHeight() / 2
				- (float) Math.sin(angle)
				* MINUTESHAND_LENGTH * radius, handPaint);
		
		angle = Math.PI / 2 - (mHour / 12.0f + mMinutes / 1440.0f) * Math.PI;
		
		canvas.drawLine(getWidth() / 2, getHeight() / 2, // Origin
				getWidth() / 2 + (float) Math.cos(angle) // Angle
						* HOURSHAND_LENGTH * radius, // Hand length
				getHeight() / 2 - (float) Math.sin(angle) // Angle
						* HOURSHAND_LENGTH * radius, // Hand
				handPaint); // Paint

		angle = Math.PI / 2 - mSeconds / 30.0f * Math.PI;
		
		canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2
				+ (float) (Math.cos(angle)
						* SECONDSHAND_LENGTH * radius), getHeight() / 2
				- (float) Math.sin(angle)
				* SECONDSHAND_LENGTH * radius, handSecondaryPaint);

		// Draw events
		for (int i = 0; i < events.size(); i++) {

			eventPaint.setColor(events.get(i).getEvent().getCategory().getColor());

			float length = (float) Math.sqrt(Math.pow(getWidth() / 2, 2)
					+ Math.pow(getHeight() / 2, 2));

			float[] coordinatesOffset = { length , 0 };
			Matrix rotationMatrix = new Matrix();
			rotationMatrix.setRotate(eventAngles.get(i));
			rotationMatrix.mapPoints(coordinatesOffset);

			canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2
					+ coordinatesOffset[0], getHeight() / 2
					- coordinatesOffset[1], eventPaint);
		}

		if (scaled) {
			canvas.restore();
		}

	}

}
